package com.wh.minihelp.user.service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.ServletException;

import org.apache.commons.lang.StringUtils;

import com.wh.db.sql.SQLUtils;
import com.wh.json.JSONUtil;
import com.wh.minihelp.filter.IFunctionContext;
import com.wh.minihelp.filter.IFunctionService;
import com.wh.minihelp.flower.dao.FlowerDao;
import com.wh.minihelp.flower.domain.ChildFlower;
import com.wh.minihelp.flower.domain.FamilyFlower;
import com.wh.minihelp.flower.domain.SysFlower;
import com.wh.minihelp.user.dao.UserDao;
import com.wh.minihelp.user.domain.AccountInfo;
import com.wh.minihelp.user.domain.ChildInfo;
import com.wh.minihelp.user.domain.FamilyAccount;
import com.wh.minihelp.user.domain.FamilyInfo;
import com.wh.minihelp.user.util.UserUtil;
import com.wh.web.util.lang.StringUtil;

/**
 * 实现用户相关操作：注册、登录、绑定
 * 
 * @author washheart@163.com
 */
public class UserService implements IFunctionService {

	public static final String//
	MD_WX = "wx", // 从问下进入的页面
			MD_Reg = "R", // 执行注册
			MD_MGR = "mgr", // 管理页面
			MD_OVERVIEW = "overview", // 红花总览
			MD_ADD_Child = "AC", // 添加小孩信息
			MD_UPD_Child = "UC", // 修改小孩信息
			MD_DEL_Child = "DC", // 删除小孩信息
			MD_SET_USER = "SU", // 设置家庭成员
			MD_DEL_USER = "DU", // 删除家庭成员
			MD_CREATE_OR_JOIN_FAMILY = "family", //
			MD_GOTO_FAMILY = "GF", // 进入指定家庭
			MD_LEAVE_FAMILY = "LF", // 退出某个家庭
			MD_SETDEFAULT_FAMILY = "SDF", // 设置某个家庭为默认家庭
			MD_pwd = "pwd", //
			MD_login = "login", //
			MD_toBind = "tB"; // 打开绑定页面

	public static final String Module = "u";

	private UserDao dao;

	private IFunctionContext ctx;

	private String wxId;
	private FamilyAccount curFa;

	@Override
	public void dispather(IFunctionContext fctx, String method) throws ServletException, IOException {
		this.ctx = fctx;
		this.dao = ctx.getDao(UserDao.class);
		if (MD_WX.equals(method)) {// 从微信进入后的第一个页面就是这个动作
			String wxId = ctx.getParameter("wxId");
			if (StringUtil.empty(wxId)) {
				notFromWeiXin();
			} else {
				wxId = SQLUtils.delSpecialSQLChar(wxId);
				UserUtil.setWxId(fctx, wxId);
				// 这里用sendRedirect方式以避免wxId传来传去
				ctx.sendRedirect(ctx.getRequest().getContextPath() + "/" + Module + "?m=" + MD_toBind);
			}
		} else {
			this.wxId = UserUtil.getWxId(fctx);
			if (StringUtil.empty(wxId)) {
				notFromWeiXin();
				return;
			}
			if (MD_toBind.equals(method)) {//
				fromWeiXin();
			} else if (MD_login.equals(method)) {
				jsonLogin();
			} else if (MD_OVERVIEW.equals(method)) {// 到总览页面
				gotoChildOverview();
			} else if (MD_Reg.equals(method)) {// 执行注册操作录
				regFromWeiXin();
			} else if (MD_MGR.equals(method)) {// 管理页面
				gotoMgrPage();
			} else if (MD_ADD_Child.equals(method)) {
				jsonAddChild();
			} else if (MD_UPD_Child.equals(method)) {
				jsonUpdChild();
			} else if (MD_DEL_Child.equals(method)) {
				jsonDelChild();
			} else if (MD_SET_USER.equals(method)) {
				jsonSetUser();
			} else if (MD_DEL_USER.equals(method)) {
				jsonDelUser();
			} else if (MD_CREATE_OR_JOIN_FAMILY.equals(method)) {
				jsonCreateOrJoin();
			} else if (MD_GOTO_FAMILY.equals(method)) {
				jsonGotoFamily();
			} else if (MD_LEAVE_FAMILY.equals(method)) {
				jsonLeaveFamily();
			} else if (MD_SETDEFAULT_FAMILY.equals(method)) {
				jsonSetDefaultFamily();
			} else if (MD_pwd.equals(method)) {
				jsonChangePwd();
			}
		}
	}

	private void jsonGotoFamily() throws IOException, ServletException {
		curFa = UserUtil.getUser(ctx);
		String fid = ctx.getParameter("id");// 获取家庭id
		FamilyAccount tmp = dao.getFamilyAccount(curFa == null ? UserUtil.getWxId(ctx) : curFa.getAccountId(), fid);
		if (UserUtil.isFamilyMember(ctx, tmp, true)) {
			UserUtil.setUser(ctx, tmp);
			// gotoChildOverview(tmp);// 到新家庭的总览页面(json方式传来的，只能是json方式去跳转)
			ctx.json(JSONUtil.toJsonMsg(true, null));
		}
	}

	private void jsonLeaveFamily() throws IOException, ServletException {
		curFa = UserUtil.getUser(ctx);
		String fid = ctx.getParameter("id");// 获取家庭id
		FamilyAccount tmp = dao.getFamilyAccount(curFa.getAccountId(), fid);
		if (tmp == null) {
			ctx.json(JSONUtil.toJsonMsg(false, "请选择一个有效的家庭名称！"));
			return;
		}
		tmp.setType(FamilyAccount.Deleted);
		dao.setUserType(tmp);
		if (curFa.getFamilyId().equals(fid)) {
			UserUtil.setUser(ctx, null);
		}
		ctx.json(JSONUtil.toJsonMsg(true, null, curFa.getFamilyId().equals(fid) ? "1" : "0"));
	}

	private void jsonSetDefaultFamily() throws IOException, ServletException {
		curFa = UserUtil.getUser(ctx);
		String fid = ctx.getParameter("id");// 获取家庭id
		dao.changeDefaultFamily(curFa.getAccountId(), fid);
		ctx.json(JSONUtil.toJsonMsg(true, null));
	}

	private void jsonCreateOrJoin() throws ServletException, IOException {
		String familyName = ctx.getParameter("name");// 获取家庭名称
		if (StringUtils.isEmpty(familyName)) {
			ctx.json(JSONUtil.toJsonMsg(false, "请输入一个有效的家庭名称！"));
			return;
		}
		AccountInfo acc = null;
		curFa = UserUtil.getUser(ctx);
		if (curFa == null) {
			// fromWeiXin();
			// return;
			acc = dao.getAccountByWX(wxId);
		} else {
			acc = curFa.getAccount();
		}
		boolean saveFamily = false;
		String familyOper = ctx.getParameter("familyOper");
		FamilyInfo family = dao.getFamilyByName(familyName);
		int userType = FamilyAccount.Auditing;
		if ("1".equals(familyOper)) {// 创建
			if (family != null) {
				ctx.json(JSONUtil.toJsonMsg(false, "您输入的家庭名称已存在，试试其他的吧。"));
				return;
			} else {
				family = new FamilyInfo();
				family.setId(UserUtil.genUID());
				family.setName(familyName);
				saveFamily = true;// 保存一个新的家庭
			}
			userType = FamilyAccount.CREATOR;
		} else {// 加入
			if (family == null) {
				ctx.json(JSONUtil.toJsonMsg(false, "您输入的家庭名称不存在，再核实下吧。"));
				return;
			} else {
				FamilyAccount tmp = dao.getFamilyAccount(acc.getId(), family.getId());
				if (tmp != null) {
					if (UserUtil.isFamilyMember(ctx, tmp, false)) {
						ctx.json(JSONUtil.toJsonMsg(false, "您已加入此家庭。"));
					} else {
						tmp.setType(FamilyAccount.Auditing);
						dao.setUserType(tmp);
						ctx.json(JSONUtil.toJsonMsg(true, null, tmp.toMap()));
					}
					return;
				}
			}
		}
		FamilyAccount tmp = dao.createAccount(acc, family, userType, saveFamily, false, false);
		ctx.json(JSONUtil.toJsonMsg(true, null, tmp.toMap()));
	}

	private void jsonSetUser() throws IOException, ServletException {
		this.curFa = UserUtil.getUser(ctx);
		if (!UserUtil.isFamilyCreator(ctx, curFa, true)) return;// 只有管理员才能对本家庭的成员进行操作
		String aid = ctx.getParameter("id");// 帐号id
		if (StringUtils.isEmpty(aid)) {
			ctx.json(JSONUtil.toJsonMsg(false, "请选择一个要修改的数据！"));
			return;
		}
		String sType = ctx.getParameter("type");
		int type = FamilyAccount.Deleted;// 被删除的
		try {
			type = Integer.parseInt(sType);
		} catch (Throwable e) {
			ctx.json(JSONUtil.toJsonMsg(false, "用户类型设置不正确！"));
			return;
		}
		if (type < FamilyAccount.Auditing || type > FamilyAccount.Deleted) {
			ctx.json(JSONUtil.toJsonMsg(false, "用户类型设置不正确！"));
			return;
		}
		FamilyAccount tmp = dao.getFamilyAccount(aid, this.curFa.getFamilyId());// 查出对应的数据
		if (tmp == null) {
			ctx.json(JSONUtil.toJsonMsg(false, "请选择一个要修改的数据！"));
			return;
		}
		tmp.setType(type);
		dao.setUserType(tmp);
		ctx.json(JSONUtil.toJsonMsg(true, null));
	}

	private void jsonDelUser() throws IOException, ServletException {
		this.curFa = UserUtil.getUser(ctx);
		if (!UserUtil.isFamilyCreator(ctx, curFa, true)) return;// 只有管理员才能对本家庭的成员进行操作
		String aid = ctx.getParameter("id");// 帐号id
		if (StringUtils.isEmpty(aid)) {
			ctx.json(JSONUtil.toJsonMsg(false, "请选择一个要修改的数据！"));
			return;
		}
		FamilyAccount tmp = dao.getFamilyAccount(aid, this.curFa.getFamilyId());// 查出对应的数据
		if (tmp == null) {
			ctx.json(JSONUtil.toJsonMsg(false, "请选择一个要修改的数据！"));
			return;
		}
		dao.delFamilyAccount(tmp);
		ctx.json(JSONUtil.toJsonMsg(true, null));
	}

	private void jsonAddChild() throws ServletException, IOException {
		if (!UserUtil.isFamilyManager(ctx, curFa, true)) return;
		String name = ctx.getParameter("name");// 获取小孩名称
		if (StringUtils.isEmpty(name)) {
			ctx.json(JSONUtil.toJsonMsg(false, "请输入一个有效的小孩名称！"));
			return;
		}
		ChildInfo ff = new ChildInfo();
		// ff.setAge();
		ff.setCreateDate(new Date());
		ff.setId(UserUtil.genUID());
		ff.setName(name);
		// ff.setPhoto();
		// ff.setRemark();
		// ff.setSex();
		// ff.setTotals();
		// ff.setUsed();
		ff.setFamilyId(UserUtil.getUser(ctx).getFamilyId());
		dao.createFamilyChild(ff);
		ctx.json(JSONUtil.toJsonMsg(true, null, ff));
	}

	private void jsonUpdChild() throws IOException, ServletException {
		if (!UserUtil.isFamilyCreator(ctx, curFa, true)) return;
		String id = ctx.getParameter("id");// 获取小孩名称
		if (StringUtil.empty(id)) {
			ctx.json(JSONUtil.toJsonMsg(true, null));
			return;
		}
		ChildInfo fc = dao.getFamilyChild(id);
		if (fc == null) {
			ctx.json(JSONUtil.toJsonMsg(true, null));
			return;
		}
		String name = ctx.getParameter("name");// 获取小孩名称
		if (StringUtils.isEmpty(name)) {
			ctx.json(JSONUtil.toJsonMsg(false, "请输入一个有效的小孩名称！"));
			return;
		}
		fc.setName(name);
		dao.updateFamilyChild(fc);
		ctx.json(JSONUtil.toJsonMsg(true, null));
	}

	private void jsonDelChild() throws IOException, ServletException {
		if (!UserUtil.isFamilyManager(ctx, curFa, true)) return;
		String id = ctx.getParameter("id");//
		if (StringUtil.notEmpty(id)) {
			if (dao.getChildFlowerRecordCount(id) > 0) {
				ctx.json(JSONUtil.toJsonMsg(false, "小孩已经记录了红花信息，不能删除！"));
				return;
			}
			dao.deleteChild(id);
		}
		ctx.json(JSONUtil.toJsonMsg(true, null));
	}

	private void notFromWeiXin() throws IOException {
		ctx.message("请从微信(关注)访问~");
	}

	// 从微信进入此页面
	private void fromWeiXin() throws ServletException, IOException {
		this.curFa = dao.getUserDefault(wxId);
		if (curFa != null) {// 如果有对应的帐号，那么就跳转到小孩列表页面
			ctx.forward("/WEB-INF/user/login.jsp");// 显示登录界面
		} else { // 执行注册绑定操作录
			ctx.forward("/WEB-INF/user/bind.jsp");
		}
		// FIXME:暂时不考虑其他方式的登录
		// FIXME:暂时不考虑其他方式注册后在此页面进行绑定
	}

	private void jsonLogin() throws IOException {
		FamilyAccount t = dao.getUserDefault(wxId);
		if (t == null) {// 如果有对应的帐号，那么就跳转到小孩列表页面
			ctx.json(JSONUtil.toJsonMsg(false, "请重新从微信访问。"));
			return;
		}
		String curPwd = t.getAccount().getPwd();
		if (StringUtil.empty(curPwd)) {
			ctx.json(JSONUtil.toJsonMsg(false, "您需要在公众号回复“找回密码”来设置一个新密码！"));
			return;
		}
		// 验证旧密码是否正确
		String pwd = ctx.getParameter("pwd");// 密码
		if (curPwd.equals(pwd)) {
			// 字符串完全相同
		} else {
			ctx.json(JSONUtil.toJsonMsg(false, "您输入的密码不正确。\r\n（若要找回密码，请在公众号回复“找回密码”）"));
			return;
		}
		this.curFa = t;
		UserUtil.setUser(this.ctx, curFa);
		ctx.json(JSONUtil.toJsonMsg(true, null));
	}

	private void jsonChangePwd() throws IOException {
		this.curFa = dao.getUserDefault(wxId);
		if (curFa == null) {// 如果有对应的帐号，那么就跳转到小孩列表页面
			ctx.json(JSONUtil.toJsonMsg(false, "请重新从微信访问。"));
			return;
		}
		String pwd = ctx.getParameter("pwd");// 密码
		String curPwd = curFa.getAccount().getPwd();
		if (curPwd.equals(pwd)) {
			// 字符串完全相同
		} else {
			ctx.json(JSONUtil.toJsonMsg(false, "您输入的密码不正确。\r\n（若要找回密码，请在公众号回复“找回密码”）"));
			return;
		}
		// 密码是否符合规则
		String pwd1 = ctx.getParameter("pwd1");// 密码
		if (StringUtils.isEmpty(pwd1)) {
			ctx.json(JSONUtil.toJsonMsg(false, "请输入一个有效的密码！"));
			return;
		}
		// 检查两次输入的密码是否一致
		String pwd2 = ctx.getParameter("pwd2");// 密码
		if (!pwd1.equals(pwd2)) {
			ctx.json(JSONUtil.toJsonMsg(false, "两次输入的密码不一致！"));
			return;
		}
		curFa.getAccount().setPwd(pwd2);
		dao.updateUser(curFa.getAccount());
		ctx.json(JSONUtil.toJsonMsg(true, null));
	}

	// 到红花总览页面
	private void gotoChildOverview() throws ServletException, IOException {
		this.curFa = UserUtil.getUser(ctx);
		if (curFa == null) {
			fromWeiXin();
		} else {
			gotoChildOverview(curFa);
		}
	}

	private void gotoChildOverview(FamilyAccount fac) throws ServletException, IOException {
		int t = fac.getType();
		if (t != FamilyAccount.Manger && t != FamilyAccount.CREATOR && t != FamilyAccount.ByStander) {
			gotoMgrPage();
			return;
		}
		List<FamilyFlower> flowers = ctx.getDao(FlowerDao.class).getChildFlowerTypes(curFa);
		int size = flowers.size();
		if (size == 0) {// 没有红花类别信息，需添加
			gotoMgrPage();
			return;
		}
		List<String> addFlowers = new ArrayList<String>(size);
		List<String> subFlowers = new ArrayList<String>(size);
		for (int i = 0; i < size; i++) {
			FamilyFlower f = flowers.get(i);
			if (f.getType() == SysFlower.ADD) {
				addFlowers.add(f.getName());
			} else {
				subFlowers.add(f.getName());
			}
		}
		List<ChildInfo> childs = dao.getChilds(fac);
		if (childs.size() == 0) {// 没有小孩信息，需添加小孩
			gotoMgrPage();
			return;
		}
		ctx.setRequestAttribute("addFlowers", addFlowers);
		ctx.setRequestAttribute("subFlowers", subFlowers);
		ctx.setRequestAttribute("childs", childs);
		ctx.forward("/WEB-INF/user/overview.jsp");// 多个小孩时，调整到小孩列表界面
	}

	private void gotoMgrPage() throws ServletException, IOException {
		this.curFa = UserUtil.getUser(ctx);
		// if (curFa == null) {
		// fromWeiXin();
		// return;
		// }
		if (UserUtil.isFamilyManager(ctx, curFa, false)) {
			List<ChildInfo> childs = dao.getChilds(curFa);
			// 读取小孩
			ctx.setRequestAttribute("childs", childs);
			// 读取小孩的红花类别
			List<FamilyFlower> flowers = ctx.getDao(FlowerDao.class).getChildFlowerTypes(curFa);
			ctx.setRequestAttribute("flowers", flowers);
			// 同家庭的其他人员
			List<FamilyAccount> memebers = dao.getFamilyMemebers(curFa.getFamilyId());
			ctx.setRequestAttribute("memebers", memebers);
			// } else {//
			// List<Object> tmp = new ArrayList<Object>(0);
			// ctx.setRequestAttribute("childs", tmp);
			// ctx.setRequestAttribute("flowers", tmp);
			// ctx.setRequestAttribute("families", tmp);
		}
		if (curFa != null) {// 读取关联的家庭
			List<FamilyAccount> families = dao.getAccountFamilies(curFa.getAccountId());
			ctx.setRequestAttribute("families", families);
		} else {
			ctx.setRequestAttribute("families", new ArrayList<Object>(0));
		}
		//
		ctx.forward("/WEB-INF/user/mgr.jsp");
	}

	private void regFromWeiXin() throws IOException, ServletException {
		AccountInfo acc = dao.getAccountByWX(wxId);
		this.curFa = null;
		boolean saveFamily = false;
		String name = ctx.getParameter("name");// 获取用户名称
		if (StringUtils.isEmpty(name)) {
			ctx.json(JSONUtil.toJsonMsg(false, "请输入一个有效的用户名称！"));
			return;
		}
		// 密码是否符合规则
		String pwd1 = ctx.getParameter("pwd1");// 密码
		if (StringUtils.isEmpty(pwd1)) {
			ctx.json(JSONUtil.toJsonMsg(false, "请输入一个有效的密码！"));
			return;
		}
		// 检查两次输入的密码是否一致
		String pwd2 = ctx.getParameter("pwd2");// 密码
		if (!pwd1.equals(pwd2)) {
			ctx.json(JSONUtil.toJsonMsg(false, "两次输入的密码不一致！"));
			return;
		}
		if (acc == null) {// 帐号未注册过
			String familyName = ctx.getParameter("familyName");// 获取家庭密码
			if (StringUtils.isEmpty(familyName)) {
				ctx.json(JSONUtil.toJsonMsg(false, "请输入一个有效的家庭名称！"));
				return;
			}
			String familyOper = ctx.getParameter("familyOper");
			FamilyInfo family = dao.getFamilyByName(familyName);
			int userType = FamilyAccount.Auditing;
			if ("1".equals(familyOper)) {// 创建
				if (family != null) {
					ctx.json(JSONUtil.toJsonMsg(false, "您输入的家庭名称已存在，试试其他的吧。"));
					return;
				} else {
					family = new FamilyInfo();
					family.setId(UserUtil.genUID());
					family.setName(familyName);
					saveFamily = true;// 保存一个新的家庭
				}
				userType = FamilyAccount.CREATOR;
			} else {// 加入
				if (family == null) {
					ctx.json(JSONUtil.toJsonMsg(false, "您输入的家庭名称不存在，再核实下吧。"));
					return;
				}
			}
			acc = new AccountInfo();
			acc.setId(wxId);
			acc.setName(name);
			acc.setCreateDate(new Date());
			acc.setPwd(pwd1);
			this.curFa = dao.createAccount(acc, family, userType, saveFamily, true, true);
		} else {// 帐号注册过，直接跳到默认家庭
			if (!name.equals(acc.getName())) {
				// FIXME:修改下用户名
			}
			curFa = dao.getUserDefault(acc.getId());
			if (curFa == null) {
				// FIXME:跳转到加入/创建家庭页面？
				// FIXME：跳转到加入申请页
				// FIXME：还是直接跳到管理页面？
				UserUtil.setUser(ctx, curFa);
				// gotoMgrPage();
				ctx.json(JSONUtil.toJsonMsg(false, null, 2));
				return;
			}
		}
		UserUtil.setUser(ctx, curFa);
		ctx.json(JSONUtil.toJsonMsg(true, null));
	}
}